/***************************************************************************
 *   oboe.controllers.SceneController                                      *
 *   Copyright (C) 2011 by Felipe Manga                                    *
 *   lufeboma@gmail.com                                                    *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/

package oboe.controllers
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	
	import oboe.core.Controller;
	import oboe.core.SigSlot;
	import oboe.core.SigSlotCollection;
	import oboe.math.Number3D;
	import oboe.math.Rotator;
	
	public class SceneController extends Controller
	{
		public static const _camera_position:Number3D = new Number3D(0,0,0);
		public static var _camera_rotator:Rotator;

		private var rotator:Rotator;
		
		private var childNodes:Vector.<NodeController>;
		
		protected var minimumNodeIndex:int;
		
		protected var camera_position:Number3D;
		protected var camera_rotation:Number3D;
		
		public function SceneController( displayObject:DisplayObject=null )
		{
			super(displayObject);
			this.childNodes = new Vector.<NodeController>();
			this.rotator = new Rotator(0,0,0);
			this.minimumNodeIndex = 0;
			this.camera_position = new Number3D(0,0,0);
			this.camera_rotation = new Number3D(0,0,0);
		}
		
		protected override function addChild(child:SigSlotCollection):void
		{
			if( child is NodeController ) this.childNodes.push( child );
			super.addChild( child );
		}
		
		protected override function removeChild(child:SigSlotCollection):void
		{
			if( child is NodeController )
			{
				var i:int = this.childNodes.indexOf( child );
				if( i > -1 )
				{
					this.childNodes[i] = this.childNodes[ this.childNodes.length-1 ];
					this.childNodes.pop();
				}
			}
			
			super.removeChild( child );
		}
		
		protected function render():void
		{
			if( this.camera_rotation )
			{
				_camera_rotator = this.rotator;
				if( !this.rotator.isEqual( this.camera_rotation ) )
				{
					this.rotator.copy2( -this.camera_rotation.x, -this.camera_rotation.y, -this.camera_rotation.z );
					this.rotator.update();
				}
			}
			else
			{
				_camera_rotator = null;
			}
			
			_camera_position.copy3( this.camera_position );
			
			this.childNodes.sort(
				function (a:NodeController, b:NodeController):Number
				{
					var r:Number = b.callGetZSortPosition() - a.callGetZSortPosition();
					if( r < 0 ) return -1;
					if( r > 0 ) return 1;
					return 0;
				}
			);
			
			var container:DisplayObjectContainer = this.getDisplayObject() as DisplayObjectContainer;
			var i:int = this.minimumNodeIndex;
			
			for each( var child:NodeController in this.childNodes )
			{
				container.setChildIndex( child.target, i++ );
			}
		}
	}
}